package pt.utl.ist.ginger3d;

import java.io.IOException;
import java.io.RandomAccessFile;

public class BufferedRandomAccessFile extends RandomAccessFile {

	private static int defaultBufferSize = 2048;
	private byte buffer[];
	private int bufferEnd = 0;
	private int bufferPos = 0;
	private long realPos = 0;
	private int bufSize;

	public BufferedRandomAccessFile(String filename, String mode)
			throws IOException {
		this(filename, mode, defaultBufferSize);
	}

	public BufferedRandomAccessFile(String filename, String mode, int bufSize)
			throws IOException {
		super(filename, mode);
		invalidate();
		this.bufSize = bufSize;
		buffer = new byte[bufSize];
	}

	public final int read() throws IOException {
		if (bufferPos >= bufferEnd) {
			if (fillBuffer() < 0)
				return -1;
		}
		if (bufferEnd == 0) {
			return -1;
		} else {
			return (buffer[bufferPos++] & 0xFF);
		}
	}

	public int read(byte[] b) throws IOException {
		return read(b, 0, b.length);
	}

	public int read(byte b[], int off, int len) throws IOException {
		int leftover = bufferEnd - bufferPos;
		if (len <= leftover) {
			System.arraycopy(buffer, bufferPos + off, b, off, len);
			bufferPos += len;
			return len;
		}
		for (int i = 0; i < len; i++) {
			int c = this.read();
			if (c != -1)
				b[off + i] = (byte) c;
			else {
				return i;
			}
		}
		return len;
	}

	private int fillBuffer() throws IOException {
		int n = super.read(buffer, 0, bufSize);
		if (n >= 0) {
			realPos += n;
			bufferEnd = n;
			bufferPos = 0;
		}
		return n;
	}

	private void invalidate() throws IOException {
		bufferEnd = 0;
		bufferPos = 0;
		realPos = super.getFilePointer();
	}

	public long getFilePointer() throws IOException {
		long l = realPos;
		return (l - bufferEnd + bufferPos);
	}

	public void seek(long pos) throws IOException {
		int n = (int) (realPos - pos);
		if (n >= 0 && n <= bufferEnd) {
			bufferPos = bufferEnd - n;
		} else {
			super.seek(pos);
			invalidate();
		}
	}

}
